package edu.mse.camel.client.session.wizards;

import java.util.Collections;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.ui.dialogs.WorkspaceResourceDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbench;

public class ModelDiagramPage extends WizardPage implements Listener {

	private IWorkbench workbench;
	private IStructuredSelection selection;
	
	private Text modelName;
	private Text diagramName;
	private Button modelButtonIconBrowse;
	private Button diagramButtonIconBrowse;
	private Button isPopulate;
	private Button isWhiteboard;
	private Text wbName;
	private Button wbBottonIconBrowse;

	// status variable for the possible errors on this page
	private IStatus filenameInvalidStatus;
	private IStatus diagramEmptyStatus; 
	private IStatus modelEmptyStatus;
	
	public ModelDiagramPage(String pageName, String title,
			ImageDescriptor titleImage) {
		super(pageName, title, titleImage);
		filenameInvalidStatus = new Status(IStatus.OK, "not_used", 0, "", null);
		modelEmptyStatus = new Status(IStatus.OK, "not_used", 0, "", null);
		diagramEmptyStatus = new Status(IStatus.OK, "not_used", 0, "", null);
	}

	public ModelDiagramPage(String pageName) {
		super(pageName);
		setTitle("Select a model");
		setDescription("Please select the model and diagram used for the session");
		filenameInvalidStatus = new Status(IStatus.OK, "not_used", 0, "", null);
		modelEmptyStatus = new Status(IStatus.OK, "not_used", 0, "", null);
		diagramEmptyStatus = new Status(IStatus.OK, "not_used", 0, "", null);
	}

	@Override
	public void createControl(Composite parent) {

		// create the composite to hold the widgets
		GridData gd;
		Composite composite =  new Composite(parent, SWT.NULL);

	    // create the desired layout for this wizard page
		GridLayout gl = new GridLayout();
		int ncol = 3;
		gl.numColumns = ncol;
		composite.setLayout(gl);
		
		// Session Name				
		new Label (composite, SWT.NONE).setText("Please select the model:");				
		modelName = new Text(composite, SWT.BORDER);
		gd = new GridData(GridData.FILL_HORIZONTAL);
		modelName.setLayoutData(gd);
		modelButtonIconBrowse = new Button(composite, SWT.PUSH);
		modelButtonIconBrowse.setText("Browse");
		modelButtonIconBrowse.addSelectionListener(new SelectionAdapter(){
			public void widgetSelected(SelectionEvent e){
				String ext = "uml";
				IFile[] files = selectFromWorkSpace(ext);
				if(files.length != 0)
				{
					modelName.setText(files[0].getFullPath().toPortableString());
					saveDataToModel();
					validStatus();
				}	
			}
		});
		
		// Diagram Description
		new Label (composite, SWT.NONE).setText("Please select the diagram:");
		diagramName = new Text(composite, SWT.BORDER);
		gd = new GridData(GridData.FILL_HORIZONTAL);
		diagramName.setLayoutData(gd);
		diagramButtonIconBrowse = new Button(composite, SWT.PUSH);
		diagramButtonIconBrowse.setText("Browse");
		diagramButtonIconBrowse.addSelectionListener(new SelectionAdapter(){
			public void widgetSelected(SelectionEvent e){
				String ext = "di2";
				IFile[] files = selectFromWorkSpace(ext);
				if(files.length != 0)
				{
					diagramName.setText(files[0].getFullPath().toPortableString());
					saveDataToModel();
					validStatus();
				}
			}
		});

		// Diagram Description
		new Label (composite, SWT.NONE).setText("Please select the whiteboard:");
		wbName = new Text(composite, SWT.BORDER);
		gd = new GridData(GridData.FILL_HORIZONTAL);
		wbName.setLayoutData(gd);
		wbBottonIconBrowse = new Button(composite, SWT.PUSH);
		wbBottonIconBrowse.setText("Browse");
		wbBottonIconBrowse.addSelectionListener(new SelectionAdapter(){
			public void widgetSelected(SelectionEvent e){
				String ext = "whiteboard";
				IFile[] files = selectFromWorkSpace(ext);
				if(files.length != 0)
				{
					wbName.setText(files[0].getFullPath().toPortableString());
					saveDataToModel();
					validStatus();
				}
			}
		});
		
		//check if the user wants to populate the diagram on poster board
//		isPopulate = new Button(composite, SWT.CHECK);
//		isPopulate.setText("Populate posterboard with diagram");
//		gd = new GridData(GridData.FILL_HORIZONTAL);
//		gd.horizontalSpan = ncol;
//		isPopulate.setLayoutData(gd);
		
		//check if the user wants to create a new whiteboard on poster board
//		isWhiteboard = new Button(composite, SWT.CHECK);
//		isWhiteboard.setText("Create whiteboard");
//		isWhiteboard.setSelection(true);
//		gd = new GridData(GridData.FILL_HORIZONTAL);
//		gd.horizontalSpan = ncol;
//		isWhiteboard.setLayoutData(gd);
		
	    // set the composite as the control for this page
		setControl(composite);		
		addListeners();
		((CreateSessionWizard)getWizard()).isCompleted = true; 
		setPageComplete(isPageComplete());
	}

	private void addListeners() {
		modelName.addListener(SWT.KeyUp, this);
		diagramName.addListener(SWT.KeyUp, this);
		wbName.addListener(SWT.KeyUp, this);
//		isWhiteboard.addListener(SWT.Selection, this);
	}

	@Override
	public void handleEvent(Event event) {
		saveDataToModel();
		validStatus();
		getWizard().getContainer().updateButtons();
	}

	private void validStatus() {

		// Initialize a variable with the no error status
	    Status status = new Status(IStatus.OK, "not_used", 0, "", null);
		filenameInvalidStatus = new Status(IStatus.OK, "not_used", 0, "", null);
		modelEmptyStatus = new Status(IStatus.OK, "not_used", 0, "", null);
		diagramEmptyStatus = new Status(IStatus.OK, "not_used", 0, "", null);
	    
		CreateSessionWizard wizard = (CreateSessionWizard) getWizard();
		SessionModel model = wizard.model;
		wizard.isCompleted = true;
		
		if(model.selectedModel != null && model.selectedModel.length() > 0){
			if (! validFilename(model.selectedModel)){
		    	status = new Status(IStatus.ERROR, "not_used", 0, 
		                "Invalid filename. Please enter the correct filepath", null);        
		        filenameInvalidStatus = status;	
		        setPageComplete(false);
				wizard.isCompleted = false;
			} else if (model.selectedDiagram == null || model.selectedDiagram.length() == 0) {
		    	status = new Status(IStatus.ERROR, "not_used", 0, 
		                "The diagram file cannot be empty. Please select the diagram file. ", null);        
		    	diagramEmptyStatus = status; 
				wizard.isCompleted = false;
			}
		}

		if(model.selectedDiagram != null && model.selectedDiagram.length() > 0 ){
			if (! validFilename(model.selectedDiagram)){
		    	status = new Status(IStatus.ERROR, "not_used", 0, 
		                "Invalid filename. Please enter the correct filepath", null);        
		        filenameInvalidStatus = status;
				wizard.isCompleted = false;
			} else if (model.selectedModel == null || model.selectedModel.length() == 0){
		    	status = new Status(IStatus.ERROR, "not_used", 0, 
		                "The diagram shall associate with the model. Please enter the model file. ", null);        
		    	modelEmptyStatus = status;			
				wizard.isCompleted = false;
			}
		}
	
	    // Show the most serious error
	    applyToStatusLine(findMostSevere());
		setPageComplete(isPageComplete());

	}

	private boolean validFilename(String filename) {
		if (! Path.ROOT.isValidPath(filename))
			return false;
	
		if (getFileFromWorkspaceRoot(filename) == null)
			return false;
		return true;
	}

	private IStatus findMostSevere() {
		if (filenameInvalidStatus.matches(IStatus.ERROR))
			return filenameInvalidStatus;
		if (modelEmptyStatus.matches(IStatus.ERROR))
			return modelEmptyStatus;
		return diagramEmptyStatus;
	}

	private IFile getFileFromWorkspaceRoot(String fileName) {
		if (fileName != null) {
			try{
				IPath filepath = new Path(fileName);
				IFile iFile = ResourcesPlugin.getWorkspace().getRoot().getFile(filepath);
				if (iFile.exists()) {
					return iFile;
				}
			} catch (Exception e){
				return null;
			}
		}
		return null;
	}

	@Override
	public boolean isPageComplete() {

		CreateSessionWizard wizard = (CreateSessionWizard) getWizard();
		
		if(!isTextNonEmpty(modelName) && !isTextNonEmpty(diagramName) )
			wizard.isCompleted=false;
		return wizard.isCompleted;

	}

	
	private static boolean isTextNonEmpty(Text t)
	{
		String s = t.getText();
		if ((s!=null) && (s.trim().length() >0)) return true;
		return false;
	}

	private void saveDataToModel() {
		
		CreateSessionWizard wizard = (CreateSessionWizard) getWizard();
		SessionModel model = wizard.model;
		model.selectedModel = getName(modelName);
		model.selectedDiagram = getName(diagramName);
		model.isCreateWhiteboard = true;
		model.selectedWhiteboard = getName(wbName);
//		model.isPopulate = isPopulate.getSelection();
//		model.isCreateWhiteboard = isWhiteboard.getSelection();
	}
	
	private String getName(Text textName) {
		String name = textName.getText().trim();
		if(name.length() == 0)
			return null;
		else
			return name;
	}

	@Override
	public IWizardPage getNextPage() {
		return null;
	}
	
	private IFile[] selectFromWorkSpace(final String ext) {
		
		ViewerFilter extFilter = new ViewerFilter(){
			public boolean select (Viewer viewer, Object parentElement, Object element){
				if(element instanceof IFile){
					IFile file = (IFile) element;
					return ext.equals(file.getFileExtension());
				}
				return true;
			}
		};
		
		IFile[] files = WorkspaceResourceDialog.openFileSelection(
				new Shell(), "Select model", 
				"Please select model from workspace", 
				false, null,
				Collections.singletonList(extFilter));

		return files;
	}

	/**
	 * Applies the status to the status line of a dialog page.
	 */
	private void applyToStatusLine(IStatus status) {
		String message= status.getMessage();
		if (message.length() == 0) message= null;
		switch (status.getSeverity()) {
			case IStatus.OK:
				saveDataToModel();
				setErrorMessage(null);
				setMessage(message);
				break;
			case IStatus.WARNING:
				setErrorMessage(null);
				setMessage(message, WizardPage.WARNING);
				break;				
			case IStatus.INFO:
				setErrorMessage(null);
				setMessage(message, WizardPage.INFORMATION);
				break;			
			default:
				setErrorMessage(message);
				setMessage(null);
				break;		
		}
	}	

}
